package com.qiangesoft.blog.file.core.local;

import com.qiangesoft.blog.file.config.FileStoreConfig;
import com.qiangesoft.blog.file.enums.FileStoreTypeEnum;
import com.qiangesoft.blog.file.model.FileInfoVo;
import com.qiangesoft.blog.file.utils.MimeTypeUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.FileCopyUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.file.*;
import java.time.LocalDateTime;
import java.util.Random;

/**
 * 文件服务接口
 *
 * @author qiange
 * @date 2023-04-28
 */
@Slf4j
@Service
public class LocalFileServiceImpl implements LocalFileService {

    @Autowired
    private FileStoreConfig fileStoreConfig;

    @Override
    public void validFiles(MultipartFile[] files) {
        if (null != files && files.length >= 1) {
            MultipartFile[] var2 = files;
            int currentSize = files.length;

            int uploadBatchSize;
            for (uploadBatchSize = 0; uploadBatchSize < currentSize; ++uploadBatchSize) {
                MultipartFile file = var2[uploadBatchSize];
                if (ObjectUtils.isEmpty(file) || file.isEmpty()) {
                    throw new RuntimeException("file empty");
                }
            }
        } else {
            throw new RuntimeException("files empty");
        }
    }

    @Override
    public Boolean createFolder(String folderPath) {
        Path path = Paths.get(folderPath);
        if (Files.exists(path, new LinkOption[0])) {
            log.warn("file directory=[{}] already exists", folderPath);
            return true;
        } else {
            try {
                Files.createDirectories(path);
                return true;
            } catch (IOException var4) {
                log.error("create directories path=[{}] IOException,errMsg=[{}]", folderPath, var4.getMessage());
                return false;
            }
        }
    }

    @Override
    public FileInfoVo uploadFile(MultipartFile file, String path) {
        String pathPrefix = fileStoreConfig.getLocalConfig().getBasePath();
        LocalDateTime now = LocalDateTime.now();
        String pathSuffix = now.getYear() + fileSeparator() + now.getMonthValue() + fileSeparator() + now.getDayOfMonth();
        if (StringUtils.isNotBlank(path)) {
            pathSuffix = path + fileSeparator() + pathSuffix;
        }
        String storePath = pathPrefix + fileSeparator() + pathSuffix;
        boolean createSuccess = this.createFolder(storePath);
        if (!createSuccess) {
            throw new RuntimeException("文件目录创建失败");
        } else {
            String originalFilename = file.getOriginalFilename();
            String fileExtension = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);
            String fileName = parseFileName(fileExtension);
            String filePathStr = storePath + fileSeparator() + fileName;

            try {
                Path newFilePath = FileSystems.getDefault().getPath(filePathStr);
                Files.createFile(newFilePath);
                File newFile = new File(filePathStr);
                byte[] content = file.getBytes();
                FileCopyUtils.copy(content, newFile);
            } catch (IOException var8) {
                log.error("upload file={} IOException,errMsg=[{}]", filePathStr, var8.getMessage());
                throw new RuntimeException("文件上传失败");
            }

            // 文件响应
            FileInfoVo fileInfoVo = new FileInfoVo();
            fileInfoVo.setOriginalFileName(originalFilename);
            fileInfoVo.setFileName(fileName);
            fileInfoVo.setStoreUrl(pathSuffix + fileSeparator() + fileName);
            fileInfoVo.setCategory(path);
            fileInfoVo.setFileExtension(fileExtension);
            fileInfoVo.setFileSize(file.getSize());
            fileInfoVo.setStoreType(FileStoreTypeEnum.FILE_LOCAL.getCode());
            return fileInfoVo;
        }
    }

    @Override
    public FileInfoVo uploadFile(InputStream inputStream, String contentType, String path) {
        String pathPrefix = fileStoreConfig.getLocalConfig().getBasePath();
        LocalDateTime now = LocalDateTime.now();
        String pathSuffix = now.getYear() + fileSeparator() + now.getMonthValue() + fileSeparator() + now.getDayOfMonth();
        if (StringUtils.isNotBlank(path)) {
            pathSuffix = path + fileSeparator() + pathSuffix;
        }
        String storePath = pathPrefix + fileSeparator() + pathSuffix;
        boolean createSuccess = this.createFolder(storePath);
        if (!createSuccess) {
            throw new RuntimeException("文件目录创建失败");
        } else {
            String fileExtension = MimeTypeUtils.getExtension(contentType);
            String fileName = parseFileName(fileExtension);
            String filePathStr = storePath + fileSeparator() + fileName;

            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            try {
                Path newFilePath = FileSystems.getDefault().getPath(filePathStr);
                Files.createFile(newFilePath);
                File newFile = new File(filePathStr);
                byte[] buffer = new byte[1024 * 4];
                int n = 0;
                while (-1 != (n = inputStream.read(buffer))) {
                    byteArrayOutputStream.write(buffer, 0, n);
                }
                byte[] content = byteArrayOutputStream.toByteArray();
                FileCopyUtils.copy(content, newFile);
            } catch (IOException var8) {
                log.error("upload file={} IOException,errMsg=[{}]", filePathStr, var8.getMessage());
                throw new RuntimeException("文件上传失败");
            } finally {
                try {
                    byteArrayOutputStream.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }

            // 文件响应
            FileInfoVo fileInfoVo = new FileInfoVo();
            fileInfoVo.setOriginalFileName(fileName);
            fileInfoVo.setFileName(fileName);
            fileInfoVo.setStoreUrl(pathSuffix + fileSeparator() + fileName);
            fileInfoVo.setCategory(path);
            fileInfoVo.setFileExtension(fileExtension);
            try {
                fileInfoVo.setFileSize((long) inputStream.available());
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            fileInfoVo.setStoreType(FileStoreTypeEnum.FILE_LOCAL.getCode());
            return fileInfoVo;
        }
    }

    @Override
    public byte[] downloadByFilePath(String filePath) {
        try {
            byte[] bytes = Files.readAllBytes(Paths.get(fileStoreConfig.getLocalConfig().getBasePath() + fileSeparator() + filePath));
            return bytes;
        } catch (IOException var3) {
            log.error("download file,filePath=[{}] error,errMsg=[{}]", filePath, var3.getMessage());
            throw new RuntimeException("文件下载失败");
        }
    }

    @Override
    public byte[] downloadFileByUrl(String url) {
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();

        try {
            InputStream inputStream = (new URL(url)).openStream();
            Throwable var4 = null;

            try {
                byte[] buff = new byte[1024];

                int rc;
                while ((rc = inputStream.read(buff, 0, 1024)) > 0) {
                    byteArrayOutputStream.write(buff, 0, rc);
                }
            } catch (Throwable var15) {
                var4 = var15;
                throw var15;
            } finally {
                if (inputStream != null) {
                    if (var4 != null) {
                        try {
                            inputStream.close();
                        } catch (Throwable var14) {
                            var4.addSuppressed(var14);
                        }
                    } else {
                        inputStream.close();
                    }
                }

            }
        } catch (IOException var17) {
            log.error("download file by IOException=[{}] error,errMsg=[{}]", url, var17.getMessage());
            throw new RuntimeException("文件下载失败");
        }

        return byteArrayOutputStream.toByteArray();
    }

    @Override
    public void deleteByFilePath(String filePath) {
        try {
            Files.deleteIfExists(Paths.get(filePath));
        } catch (IOException var3) {
            log.error("delete file=[{}] IOException,errMsg=[{}]", filePath, var3.getMessage());
            throw new RuntimeException("文件删除失败");
        }
    }

    /**
     * 构建文件名
     *
     * @return
     */
    private String parseFileName(String fileExtension) {
        long now = System.currentTimeMillis() / 1000;
        return now
                + "_" + new Random().nextInt(1000)
                + "."
                + fileExtension;
    }
}
